'''
Copyright 2010 Indra Bagus <indra.bagus@gmail.com> 
    
Licensed under the Apache License, Version 2.0 (the "License"); 
you may not use this file except in compliance with the License. 
You may obtain a copy of the License at 

    http://www.apache.org/licenses/LICENSE-2.0 
    
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, 
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. 
'''

from Tools import DumpBuffString
from MACHeader import MACHeaderGeneric

    

class TableInformation(object):
    def __init__(self,columnsize = 80):
        self.type = str()
        self.value_int = None
        self.value_info = str()
        self.columnsize = columnsize
        
    def __str__(self):
        retval = ''
        self.type += ' '
        self.type = self.type.ljust(self.columnsize,'.')
        retval += self.type + ' '
        if self.value_info == '' or self.value_info == None:
            retval += '0x%X' % self.value_int            
        elif self.value_int == None:
            retval += '%s' % self.value_info
        else:
            retval += '%s (0x%X)' % (self.value_info,self.value_int)

        
        return retval



class TextSection(object):
    def __init__(self,hfile,tabsize):
        self.name = str()
        self.payload = str()
        self.info = str()
        self.subsection = None
        self.tab = str().ljust(tabsize,' ')
        self.table_info = TableInformation(70 - tabsize)
        self._hfile = hfile
        self._verbosity = bool()
        
    @property
    def Verbosity(self):
        return self._verbosity
    
    @Verbosity.setter
    def Verbosity(self,value):
        self._verbosity = value
        if self.subsection is not None:
            self.subsection.Verbosity = value    
            
            
    def AddSection(self):
        if(self.subsection == None):
            self.subsection = TextSection(len(self.tab)+4)
        
        
    def GetSection(self):
        if self.subsection == None :
            self.subsection = TextSection(self._hfile,len(self.tab)+4)
            # Newly subsection should have same verbosity flag
            self.subsection.Verbosity = self._verbosity
        return self.subsection

    
    def SetInfoTable(self,infotype=str(),infovalue=int(),strval=str()):
        self.table_info.type = infotype
        self.table_info.value_info = strval
        self.table_info.value_int = infovalue
        self._hfile.write(self.tab + str(self.table_info) )
        self._hfile.write('\n')
        if(self._verbosity == True):print self.tab+str(self.table_info)
        
    def SetSectionName(self,name=str()):
        self.name = self.tab + '[' + name + '] \n'
        self._hfile.write(self.name)
        self._hfile.write('\n')
        if(self._verbosity):print self.name        

        
    def SetSectionPayload(self,pdu=str()):
        self.payload = self._tab + DumpBuffString(pdu) + '\n'
        self._hfile.write(self.payload)
        self._hfile.write('\n')
        if(self._verbosity):print self.payload        
        
 

class TextOutput(object):
    def __init__(self,outputfilename='distiller.log'):
        self._header = str().ljust(80,'-') 
        self._footer = self._header
        self._pdu_payload = ''
        self._pdu_name = ''
        self._handlefile = open(outputfilename,'w')
        self._handlefile.write(''\
        '================================================================================\n'\
        '                         IEEE Std 802.16-e Packet Distiller                     \n'\
        '================================================================================\n'\
        '\n'
        )
        self._section = TextSection(self._handlefile,4)
        self._verbosity = bool()
        
    @property
    def Verbosity(self):
        return self._verbosity
    
    @Verbosity.setter
    def Verbosity(self,value):
        self._verbosity = value      
        self._section.Verbosity = value  
        
    def BeginOutput(self):
        self._handlefile.write(self._header)
        self._handlefile.write('\n')
        if(self._verbosity):print self._header
        self.AddLine()

        
    def PrintPDUPayload(self,pdu=str()):
        self._pdu_payload = DumpBuffString(pdu)
        self._handlefile.write(self._pdu_payload)
        self._handlefile.write('\n')
        if(self._verbosity):print self._pdu_payload

    
    def PrintPDUName(self,name=str()):
        underline = str().ljust(len(name),'=')
        self._pdu_name = name + '\n'+underline
        self._handlefile.write(self._pdu_name)
        self._handlefile.write('\n')
        if(self._verbosity):print self._pdu_name


    def PrintMACHeaderGeneric(self,macheader=MACHeaderGeneric()):
        self.GetSection().SetSectionName('MAC Header')
        self.GetSection().SetInfoTable('Header Type',
                                        int(macheader.header_type.val), 
                                        str(macheader.header_type))
        self.GetSection().SetInfoTable('Encryption',
                                       int(macheader.encryption.val), 
                                       str(macheader.encryption))        
        self.GetSection().SetInfoTable('Encoding type',int(macheader.encoding_type))
        
        # Print subsection        
        subsection = self.GetSection().GetSection()
        subsection.SetInfoTable('Reserved',int(macheader.encoding_type.reserved))
        subsection.SetInfoTable('ARQ Feedback',
                                int(macheader.encoding_type.arq_feedback),
                                str(macheader.encoding_type.arq_feedback))
        subsection.SetInfoTable('Extended Type',
                                int(macheader.encoding_type.extended_type),
                                str(macheader.encoding_type.extended_type))
        subsection.SetInfoTable('Fragmentation Subheader',
                                int(macheader.encoding_type.frag_subheader),
                                str(macheader.encoding_type.frag_subheader))
        subsection.SetInfoTable('Packing Subheader',
                                int(macheader.encoding_type.packing_subheader),
                                str(macheader.encoding_type.packing_subheader))
        subsection.SetInfoTable('Fast Feedback Allocation Subheader',
                                int(macheader.encoding_type.fast_feedback_alloc_subheader),
                                str(macheader.encoding_type.fast_feedback_alloc_subheader))

        self.GetSection().SetInfoTable('ESF', int(macheader.esf), str(macheader.esf))
        self.GetSection().SetInfoTable('CRC Indicator', int(macheader.crc_indicator), 
                                       str(macheader.crc_indicator))
        self.GetSection().SetInfoTable('EKS', int(macheader.eks), str(macheader.eks))
        self.GetSection().SetInfoTable('Reserved', int(macheader.reserved))
        self.GetSection().SetInfoTable('PDU Length', int(macheader.pdu_length),str(macheader.pdu_length))
        self.GetSection().SetInfoTable('CID', int(macheader.cid))
        self.GetSection().SetInfoTable('HCS', int(macheader.hcs),str(macheader.hcs))
                                        
    
    def PrintCRC(self,calc_crc,current_crc):
        if calc_crc != current_crc:
            self.GetSection().SetInfoTable('Cyclic Redundancy Check',int(current_crc),
                                                        'Invalid CRC, should be 0x%X' % (calc_crc))
        else:
            self.GetSection().SetInfoTable('Cyclic Redundancy Check',int(current_crc),'Valid CRC')                
    
    def GetSection(self):
        return self._section

    
    def AddLine(self):
        self._handlefile.write('\n')
        if(self._verbosity):print '\n'
        
    def WriteLine(self,strline):
        assert(isinstance(strline,str))
        self._handlefile.write(strline)
        self._handlefile.write('\n')
        self._handlefile.flush()
        if(self._verbosity):print strline
    
    
        
    
    
